{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Definitions"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": [
    "n = 6\n",
    "ob, cb = '{', '}'"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Get function arguments"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "inps = \"\"\n",
    "for i in range(n) :\n",
    "    st = \"\"\n",
    "    for j in range(4) :\n",
    "        st += f\"int32_pl inp{i+1}s{j+1}, \"\n",
    "    st += f\"int64_al[inp{i+1}s1][inp{i+1}s2][inp{i+1}s3][inp{i+1}s4] inp{i+1}, \"\n",
    "    \n",
    "    inps += st\n",
    "\n",
    "# print(inps)\n",
    "args = f\"int32_pl s1, int32_pl s2, int32_pl s3, int32_pl s4, {inps}int32_pl axis, int64_al[s1][s2][s3][s4] outp\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Get function signature"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [],
   "source": [
    "func_name = f\"Concat{n}T{'4'*(n+1)}\"\n",
    "func_signature = f\"def void {func_name} ({args})\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Axis Body"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [],
   "source": [
    "def get_axis_body_(i, n, axis) :\n",
    "    ax1 = axis+1\n",
    "    \n",
    "    sub_ind = f\"i{ax1}\"\n",
    "    for j in range(1, i) :\n",
    "        sub_ind += f\"-inp{j}s{ax1}\"\n",
    "\n",
    "    if ax1 == 1 :\n",
    "        sq_braks = f\"[{sub_ind}][i2][i3][i4]\"\n",
    "    elif ax1 == 2 :\n",
    "        sq_braks = f\"[i1][{sub_ind}[i3][i4]\"\n",
    "    elif ax1 == 3 :\n",
    "        sq_braks = f\"[i1][i2][{sub_ind}][i4]\"\n",
    "    else :\n",
    "        sq_braks = f\"[i1][i2][i3][{sub_ind}]\"\n",
    "        \n",
    "    assgn_stmt = f\"outp[i1][i2][i3][i4] = inp{i}{sq_braks}\"\n",
    "    \n",
    "    if i == n :            \n",
    "        return assgn_stmt\n",
    "    else :\n",
    "        summ = f\"inp1s{ax1}\"\n",
    "        for j in range(2, i+1) :\n",
    "            summ += f\"+inp{j}s{ax1}\"\n",
    "        \n",
    "        else_body = get_axis_body_(i+1, n, axis)\n",
    "        if_else = f\"\\\n",
    "if (i{ax1} < ({summ})) {ob}\\n\\\n",
    "{assgn_stmt}\\n\\\n",
    "{cb}\\n\\\n",
    "else {ob}\\n\\\n",
    "{else_body}\\n\\\n",
    "{cb} ;\\n\"\n",
    "        return if_else\n",
    "    \n",
    "def get_axis_body(n, axis) :\n",
    "    return get_axis_body_(1, n, axis)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Get conditional body"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [],
   "source": [
    "axis_body = [get_axis_body(n, ax) for ax in range(4)]\n",
    "\n",
    "cond_body = f\"\\\n",
    "if (axis==0) {ob}\\n\\\n",
    "    {axis_body[0]}\\n\\\n",
    "{cb}\\n\\\n",
    "    else {ob} if (axis==1) {ob}\\n\\\n",
    "    {axis_body[1]}\\n\\\n",
    "{cb}\\n\\\n",
    "    else {ob} if (axis==2) {ob}\\n\\\n",
    "    {axis_body[2]}\\n\\\n",
    "{cb}\\n\\\n",
    "    else {ob}\\n\\\n",
    "    {axis_body[3]}\\n\\\n",
    "{cb} ;\\n\\\n",
    "{cb} ;\\n\\\n",
    "{cb} ;\\n\\\n",
    "{cb} ;\\n\\\n",
    "\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Get loop"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [],
   "source": [
    "func_body = f\"\\\n",
    "for i1=[0:s1] {ob}\\n\\\n",
    "for i2=[0:s2] {ob}\\n\\\n",
    "for i3=[0:s3] {ob}\\n\\\n",
    "for i4=[0:s4] {ob}\\n\\\n",
    "{cond_body}\\n\\\n",
    "{cb} ;\\n\\\n",
    "{cb} ;\\n\\\n",
    "{cb} ;\\n\\\n",
    "{cb} ;\\n\\\n",
    "\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Get total function"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "def void Concat6T4444444 (int32_pl s1, int32_pl s2, int32_pl s3, int32_pl s4, int32_pl inp1s1, int32_pl inp1s2, int32_pl inp1s3, int32_pl inp1s4, int64_al[inp1s1][inp1s2][inp1s3][inp1s4] inp1, int32_pl inp2s1, int32_pl inp2s2, int32_pl inp2s3, int32_pl inp2s4, int64_al[inp2s1][inp2s2][inp2s3][inp2s4] inp2, int32_pl inp3s1, int32_pl inp3s2, int32_pl inp3s3, int32_pl inp3s4, int64_al[inp3s1][inp3s2][inp3s3][inp3s4] inp3, int32_pl inp4s1, int32_pl inp4s2, int32_pl inp4s3, int32_pl inp4s4, int64_al[inp4s1][inp4s2][inp4s3][inp4s4] inp4, int32_pl inp5s1, int32_pl inp5s2, int32_pl inp5s3, int32_pl inp5s4, int64_al[inp5s1][inp5s2][inp5s3][inp5s4] inp5, int32_pl inp6s1, int32_pl inp6s2, int32_pl inp6s3, int32_pl inp6s4, int64_al[inp6s1][inp6s2][inp6s3][inp6s4] inp6, int32_pl axis, int64_al[s1][s2][s3][s4] outp) {\n",
      "for i1=[0:s1] {\n",
      "for i2=[0:s2] {\n",
      "for i3=[0:s3] {\n",
      "for i4=[0:s4] {\n",
      "if (axis==0) {\n",
      "    if (i1 < (inp1s1)) {\n",
      "outp[i1][i2][i3][i4] = inp1[i1][i2][i3][i4]\n",
      "}\n",
      "else {\n",
      "if (i1 < (inp1s1+inp2s1)) {\n",
      "outp[i1][i2][i3][i4] = inp2[i1-inp1s1][i2][i3][i4]\n",
      "}\n",
      "else {\n",
      "if (i1 < (inp1s1+inp2s1+inp3s1)) {\n",
      "outp[i1][i2][i3][i4] = inp3[i1-inp1s1-inp2s1][i2][i3][i4]\n",
      "}\n",
      "else {\n",
      "if (i1 < (inp1s1+inp2s1+inp3s1+inp4s1)) {\n",
      "outp[i1][i2][i3][i4] = inp4[i1-inp1s1-inp2s1-inp3s1][i2][i3][i4]\n",
      "}\n",
      "else {\n",
      "if (i1 < (inp1s1+inp2s1+inp3s1+inp4s1+inp5s1)) {\n",
      "outp[i1][i2][i3][i4] = inp5[i1-inp1s1-inp2s1-inp3s1-inp4s1][i2][i3][i4]\n",
      "}\n",
      "else {\n",
      "outp[i1][i2][i3][i4] = inp6[i1-inp1s1-inp2s1-inp3s1-inp4s1-inp5s1][i2][i3][i4]\n",
      "} ;\n",
      "\n",
      "} ;\n",
      "\n",
      "} ;\n",
      "\n",
      "} ;\n",
      "\n",
      "} ;\n",
      "\n",
      "}\n",
      "    else { if (axis==1) {\n",
      "    if (i2 < (inp1s2)) {\n",
      "outp[i1][i2][i3][i4] = inp1[i1][i2[i3][i4]\n",
      "}\n",
      "else {\n",
      "if (i2 < (inp1s2+inp2s2)) {\n",
      "outp[i1][i2][i3][i4] = inp2[i1][i2-inp1s2[i3][i4]\n",
      "}\n",
      "else {\n",
      "if (i2 < (inp1s2+inp2s2+inp3s2)) {\n",
      "outp[i1][i2][i3][i4] = inp3[i1][i2-inp1s2-inp2s2[i3][i4]\n",
      "}\n",
      "else {\n",
      "if (i2 < (inp1s2+inp2s2+inp3s2+inp4s2)) {\n",
      "outp[i1][i2][i3][i4] = inp4[i1][i2-inp1s2-inp2s2-inp3s2[i3][i4]\n",
      "}\n",
      "else {\n",
      "if (i2 < (inp1s2+inp2s2+inp3s2+inp4s2+inp5s2)) {\n",
      "outp[i1][i2][i3][i4] = inp5[i1][i2-inp1s2-inp2s2-inp3s2-inp4s2[i3][i4]\n",
      "}\n",
      "else {\n",
      "outp[i1][i2][i3][i4] = inp6[i1][i2-inp1s2-inp2s2-inp3s2-inp4s2-inp5s2[i3][i4]\n",
      "} ;\n",
      "\n",
      "} ;\n",
      "\n",
      "} ;\n",
      "\n",
      "} ;\n",
      "\n",
      "} ;\n",
      "\n",
      "}\n",
      "    else { if (axis==2) {\n",
      "    if (i3 < (inp1s3)) {\n",
      "outp[i1][i2][i3][i4] = inp1[i1][i2][i3][i4]\n",
      "}\n",
      "else {\n",
      "if (i3 < (inp1s3+inp2s3)) {\n",
      "outp[i1][i2][i3][i4] = inp2[i1][i2][i3-inp1s3][i4]\n",
      "}\n",
      "else {\n",
      "if (i3 < (inp1s3+inp2s3+inp3s3)) {\n",
      "outp[i1][i2][i3][i4] = inp3[i1][i2][i3-inp1s3-inp2s3][i4]\n",
      "}\n",
      "else {\n",
      "if (i3 < (inp1s3+inp2s3+inp3s3+inp4s3)) {\n",
      "outp[i1][i2][i3][i4] = inp4[i1][i2][i3-inp1s3-inp2s3-inp3s3][i4]\n",
      "}\n",
      "else {\n",
      "if (i3 < (inp1s3+inp2s3+inp3s3+inp4s3+inp5s3)) {\n",
      "outp[i1][i2][i3][i4] = inp5[i1][i2][i3-inp1s3-inp2s3-inp3s3-inp4s3][i4]\n",
      "}\n",
      "else {\n",
      "outp[i1][i2][i3][i4] = inp6[i1][i2][i3-inp1s3-inp2s3-inp3s3-inp4s3-inp5s3][i4]\n",
      "} ;\n",
      "\n",
      "} ;\n",
      "\n",
      "} ;\n",
      "\n",
      "} ;\n",
      "\n",
      "} ;\n",
      "\n",
      "}\n",
      "    else {\n",
      "    if (i4 < (inp1s4)) {\n",
      "outp[i1][i2][i3][i4] = inp1[i1][i2][i3][i4]\n",
      "}\n",
      "else {\n",
      "if (i4 < (inp1s4+inp2s4)) {\n",
      "outp[i1][i2][i3][i4] = inp2[i1][i2][i3][i4-inp1s4]\n",
      "}\n",
      "else {\n",
      "if (i4 < (inp1s4+inp2s4+inp3s4)) {\n",
      "outp[i1][i2][i3][i4] = inp3[i1][i2][i3][i4-inp1s4-inp2s4]\n",
      "}\n",
      "else {\n",
      "if (i4 < (inp1s4+inp2s4+inp3s4+inp4s4)) {\n",
      "outp[i1][i2][i3][i4] = inp4[i1][i2][i3][i4-inp1s4-inp2s4-inp3s4]\n",
      "}\n",
      "else {\n",
      "if (i4 < (inp1s4+inp2s4+inp3s4+inp4s4+inp5s4)) {\n",
      "outp[i1][i2][i3][i4] = inp5[i1][i2][i3][i4-inp1s4-inp2s4-inp3s4-inp4s4]\n",
      "}\n",
      "else {\n",
      "outp[i1][i2][i3][i4] = inp6[i1][i2][i3][i4-inp1s4-inp2s4-inp3s4-inp4s4-inp5s4]\n",
      "} ;\n",
      "\n",
      "} ;\n",
      "\n",
      "} ;\n",
      "\n",
      "} ;\n",
      "\n",
      "} ;\n",
      "\n",
      "} ;\n",
      "} ;\n",
      "} ;\n",
      "} ;\n",
      "\n",
      "} ;\n",
      "} ;\n",
      "} ;\n",
      "} ;\n",
      "\n",
      "}\n",
      "\n"
     ]
    }
   ],
   "source": [
    "total = f\"\\\n",
    "{func_signature} {ob}\\n\\\n",
    "{func_body}\\n\\\n",
    "{cb}\\n\\\n",
    "\"\n",
    "\n",
    "print(total)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
